package com.appspot.graph_wave;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.google.wave.api.AbstractRobotServlet;
import com.google.wave.api.Blip;
import com.google.wave.api.Event;
import com.google.wave.api.EventType;
import com.google.wave.api.Gadget;
import com.google.wave.api.GadgetView;
import com.google.wave.api.RobotMessageBundle;
import com.google.wave.api.TextView;
import com.google.wave.api.Wavelet;

@SuppressWarnings("serial")
public class RobotServlet extends AbstractRobotServlet {

	static final String webdotUrl = "http://webdot.elliottslaughter.net/webdot/";
	static final String sourceUrl = "http://graph-wave.appspot.com/data/source/";
	static final String gadgetUrl = "http://graph-wave.appspot.com/gadgets/";

	@Override
	public void processEvents(RobotMessageBundle bundle) {
		Wavelet wavelet = bundle.getWavelet();

		if (bundle.wasSelfAdded()) {
			onRobotAdded(wavelet);
		}

		for (Event e : bundle.getEvents()) {
			if (e.getType() == EventType.DOCUMENT_CHANGED) {
				onDocumentChanged(wavelet, e);
			}
		}
	}

	public void onRobotAdded(Wavelet wavelet) {
		Blip blip = wavelet.appendBlip();
		TextView textView = blip.getDocument();
		textView
				.replace("Hi. My name is Graphy and I'm here to help you presenting graphs in waves. "
						+ "Just put #!dot at the top of a blip and enter edges like a -> b.");
	}

	private static final Pattern validDotPattern = Pattern
			.compile("\\w\\W*->\\W*\\w");
	private static final Pattern gadgetIdPattern = Pattern
			.compile(".*/(\\d+)\\.xml");

	public void onDocumentChanged(Wavelet wavelet, Event event) {
		Blip blip = event.getBlip();
		TextView textView = blip.getDocument();
		GadgetView gadgetView = textView.getGadgetView();
		String inputText = textView.getText();

		// Generate graphs for blips that start with #!dot
		if (inputText.startsWith("#!dot")) {
			// Try to parse something from the blip text
			ArrayList<String> outputLines = new ArrayList<String>();
			outputLines.add("digraph {");
			String[] inputLines = inputText.split("\\n");
			for (String line : inputLines) {
				// if (!line.startsWith("\"")) textView.append("\n\"" + line +
				// "\"");
				if (validDotPattern.matcher(line).find()) {
					outputLines.add(line);
				}
			}
			outputLines.add("}");

			// If any lines were valid, serialize and update the graph
			if (outputLines.size() > 2) {
				String outputText = "";
				for (String outputLine : outputLines) {
					outputText += outputLine + "\n";
				}
				Gadget oldGadget = findGadget(gadgetView.getGadgets(),
						gadgetUrl);
				Long oldId = 0L;
				Graph oldGraph = null;
				try {
					if (oldGadget != null) {
						Matcher m = gadgetIdPattern.matcher(oldGadget.getUrl());
						if (m.matches()) {
							oldId = Long.parseLong(m.group(1));
							oldGraph = Graph.retrieveContent(oldId);
						}
					}
				} catch (NumberFormatException e) {
				}
				if (oldGraph == null
						|| !outputText.equals(oldGraph.getContent())) {
					Long id = Graph.addContent(outputText).getId();
					if (oldGadget != null) {
						gadgetView.delete(oldGadget);
						Graph.deleteContent(oldId);
					}
					Gadget newGadget = new Gadget(gadgetUrl + id + ".xml");
					gadgetView.append(newGadget);
				}
			}
		}
	}

	private Gadget findGadget(List<Gadget> gadgets, String prefix) {
		for (Gadget g : gadgets) {
			if (g.getUrl().startsWith(prefix)) {
				return g;
			}
		}
		return null;
	}
}